package com.udima.reglocation;

import java.util.Arrays;
import java.util.Collection;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.udima.reglocation.entities.UserSession;
import com.udima.reglocation.entities.VehicleType;
import com.udima.reglocation.helpers.JSONHelper;
import com.udima.reglocation.util.AsyncTaskCompleteListener;
import com.udima.reglocation.util.HttpAsyncTask;
import com.udima.reglocation.util.LogHelper;
import com.udima.reglocation.util.PreferencesHandler;
import com.udima.reglocation.util.UserSessionHandler;

public class ConfigureUserActivity extends Activity implements AsyncTaskCompleteListener {

	private Activity activity = this;

	private static final VehicleType[] vehicleTypes = { VehicleType.STANDARD, VehicleType.SPORT, VehicleType.SUV, VehicleType.MOTO,
			VehicleType.SCOOTER };

	private EditText inputUserUserName;
	private EditText inputUserFirstName;
	private EditText inputUserLastName;
	private EditText inputUserEmail;
	private Spinner inputUserVehicleType;
	private EditText inputUserFetchGpsLapseTime;

	private Button btnStoreData;
	private Button btnCancel;

	private static TextView generalErrorMsg;

	/**
	 * En la creación de la clase se instancian los objetos del formulario y se
	 * crean las funciones de escucha para los botones
	 */
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.configure_user_activity);

		inputUserUserName = (EditText) findViewById(R.id.inputUserUserName);
		inputUserFirstName = (EditText) findViewById(R.id.inputUserFirstName);
		inputUserLastName = (EditText) findViewById(R.id.inputUserLastName);
		inputUserEmail = (EditText) findViewById(R.id.inputUserEmail);
		inputUserFetchGpsLapseTime = (EditText) findViewById(R.id.inputUserFetchGpsLapseTime);
		inputUserVehicleType = (Spinner) findViewById(R.id.inputUserVehicle);
		ArrayAdapter<VehicleType> spinnerAdapter = new ArrayAdapter<VehicleType>(activity, android.R.layout.simple_spinner_item, vehicleTypes);
		inputUserVehicleType.setAdapter(spinnerAdapter);

		generalErrorMsg = (TextView) findViewById(R.id.configureUserGeneralErrorMsg);

		// Listener del boton grabar
		btnStoreData = (Button) findViewById(R.id.btnUserStoreData);
		btnStoreData.setOnClickListener(new View.OnClickListener() {
			public void onClick(View view) {
				storeUserData();
			}
		});

		// Listener del boton cancelar
		btnCancel = (Button) findViewById(R.id.btnUserCancelEdit);
		btnCancel.setOnClickListener(new View.OnClickListener() {
			public void onClick(View view) {
				Intent itemintent = new Intent(ConfigureUserActivity.this, TrackMenuActivity.class);
				ConfigureUserActivity.this.startActivity(itemintent);
			}
		});

		// lectura de los datos actuales del usuario
		readActualUserData();
	}

	/*--------------------------------------------*/

	/**
	 * 
	 */
	private void readActualUserData() {

		UserSessionHandler ush = new UserSessionHandler(getApplicationContext());
		UserSession session = ush.retrieveUserSession();
		if (session == null) {
			Intent i = new Intent(getBaseContext(), LoginActivity.class);
			startActivity(i);
		} else {

			PreferencesHandler ph = new PreferencesHandler(getApplicationContext());
			String appBaseUrl = ph.retrieveAppBaseUrl();

			JSONObject jsonReq = new JSONObject();
			JSONObject jsonUserSession = new JSONObject();
			try {
				jsonUserSession.put("userId", session.getUserId());
				jsonUserSession.put("sessionToken", session.getSessionToken());
				jsonReq.put("userSession", jsonUserSession);
				jsonReq.put("userId", session.getUserId());
			} catch (JSONException e) {
				Toast.makeText(getBaseContext(), "Error grave!! Revise el log de la aplicación", Toast.LENGTH_LONG).show();
				LogHelper.logError("Error parsing json result", e);
			}

			// Definición del callback particular para la recuperacion de datos
			// de usuario
			final AsyncTaskCompleteListener callback = new AsyncTaskCompleteListener() {

				@Override
				public void onTaskComplete(String result) {

					if (HttpAsyncTask.CONNECTIONERROR.equals(result)) {
						Toast.makeText(getBaseContext(), "Error conectando con el servidor", Toast.LENGTH_LONG).show();
					} else {

						// Primero se transforma el resultado a un objeto Json
						try {
							JSONObject json = new JSONObject(result);

							if (json.getString("responseSuccessful") == "true") {

								JSONObject jsonUser = json.getJSONObject("user");
								inputUserUserName.setText(jsonUser.getString("userName"));
								inputUserFirstName.setText(jsonUser.getString("firstName"));
								inputUserLastName.setText(jsonUser.getString("lastName"));
								inputUserEmail.setText(jsonUser.getString("email"));

								VehicleType vehicleType = VehicleType.valueOf(jsonUser.getString("vehicleType"));
								inputUserVehicleType.setSelection(Arrays.binarySearch(vehicleTypes, vehicleType));

								inputUserFetchGpsLapseTime.setText(jsonUser.getString("fetchGpsLapseTime"));

							} else {
								generalErrorMsg.setText("Error:" + json.getString("responseErrors"));
							}
						} catch (JSONException e) {
							Toast.makeText(getBaseContext(), "Error grave!! Revise el log de la aplicación", Toast.LENGTH_LONG).show();
							LogHelper.logError("Error parsing json result", e);
						}
					}
				}
			};

			// Ejecución de la consulta al servicio rest de lectura de usuario
			new HttpAsyncTask(activity) {
				@Override
				protected void onPostExecute(String result) {
					super.onPostExecute(result);
					callback.onTaskComplete(result);
				}
			}.execute(appBaseUrl + "/rest/users", jsonReq.toString());

		}
	}

	/**
	 * 
	 */
	private void storeUserData() {
		SharedPreferences pref = getApplicationContext().getSharedPreferences("com.udima.reglocation", MODE_PRIVATE);

		UserSessionHandler ush = new UserSessionHandler(getApplicationContext());
		UserSession session = ush.retrieveUserSession();
		if (session == null) {
			// No hay sesión. Se redirige al usuario a la ventana de login
			Intent i = new Intent(getBaseContext(), LoginActivity.class);
			startActivity(i);
		} else {

			JSONObject jsonReq = new JSONObject();
			JSONObject jsonUserSession = new JSONObject();
			JSONObject jsonUser = new JSONObject();
			try {
				jsonUserSession.put("userId", session.getUserId());
				jsonUserSession.put("sessionToken", session.getSessionToken());
				jsonReq.put("userSession", jsonUserSession);

				// user data
				jsonUser.put("id", session.getUserId());
				jsonUser.put("userName", inputUserUserName.getText().toString());
				jsonUser.put("firstName", inputUserFirstName.getText().toString());
				jsonUser.put("lastName", inputUserLastName.getText().toString());
				jsonUser.put("email", inputUserEmail.getText().toString());

				VehicleType vt = (VehicleType) inputUserVehicleType.getSelectedItem();
				jsonUser.put("vehicleType", vt.name());

				jsonUser.put("fetchGpsLapseTime", inputUserFetchGpsLapseTime.getText().toString());

				jsonReq.put("user", jsonUser);

			} catch (JSONException e) {
				Toast.makeText(getBaseContext(), "Error grave!! Revise el log de la aplicación", Toast.LENGTH_LONG).show();
				LogHelper.logError("Error parsing json result", e);
			}

			// Definición del callback particular para la grabacion de datos
			// de usuario
			final AsyncTaskCompleteListener callback = new AsyncTaskCompleteListener() {

				@Override
				public void onTaskComplete(String result) {
					if (HttpAsyncTask.CONNECTIONERROR.equals(result)) {
						Toast.makeText(getBaseContext(), "Error conectando con el servidor", Toast.LENGTH_LONG).show();
					} else {
						// Primero se transforma el resultado a un objeto Json
						try {
							JSONObject json = new JSONObject(result);

							if (json.getString("responseSuccessful") == "true") {
								Toast.makeText(getBaseContext(), "Datos grabados correctamente", Toast.LENGTH_SHORT).show();
							} else {
								Toast.makeText(getBaseContext(), "Hay errores en los datos introducidos. Por favor, revíselos.", Toast.LENGTH_LONG)
										.show();
								processResponseErrors(json.getJSONArray("responseErrors"));
							}
						} catch (JSONException e) {
							Toast.makeText(getBaseContext(), "Error grave!! Revise el log de la aplicación", Toast.LENGTH_LONG).show();
							LogHelper.logError("Error parsing json result", e);
						}
					}
				}
			};

			// Ejecución de la consulta al servicio rest de grabación de usuario
			new HttpAsyncTask(activity) {
				@Override
				protected void onPostExecute(String result) {
					super.onPostExecute(result);
					callback.onTaskComplete(result);
				}
			}.execute(pref.getString("appBaseUrl", null) + "/rest/users/update", jsonReq.toString());

		}
	}

	/**
	 * 
	 * @param errors
	 * @throws JSONException
	 */
	private void processResponseErrors(JSONArray errors) throws JSONException {

		hideAllResponseErrorMessages();

		JSONHelper jHelper = new JSONHelper();
		Collection<String> errs = jHelper.JSONArrayToStringCollection(errors);

		for (String err : errs) {

			TextView tv = null;

			if (err.equals("FIRSTNAME_BLANK")) {
				tv = (TextView) findViewById(R.id.errorUserFirstName);
				tv.setVisibility(TextView.VISIBLE);
				tv.setText("Introduzca el nombre");
			} else if (err.contains("LASTNAME_BLANK")) {
				tv = (TextView) findViewById(R.id.errorUserLastName);
				tv.setVisibility(TextView.VISIBLE);
				tv.setText("Introduzca los apellidos");
			} else if (err.contains("EMAIL_BLANK")) {
				tv = (TextView) findViewById(R.id.errorUserEmail);
				tv.setVisibility(TextView.VISIBLE);
				tv.setText("Introduzca el email");
			} else if (err.contains("EMAIL_INCORRECT")) {
				tv = (TextView) findViewById(R.id.errorUserEmail);
				tv.setVisibility(TextView.VISIBLE);
				tv.setText("El email tiene un formato incorrecto");
			} else if (err.contains("VEHICLETYPE_BLANK")) {
				tv = (TextView) findViewById(R.id.errorUserVehicleType);
				tv.setVisibility(TextView.VISIBLE);
				tv.setText("Introduzca el tipo de vehículo");
			} else if (err.contains("GPSFETCHTIME_BLANK")) {
				tv = (TextView) findViewById(R.id.errorUserGpsFetchTime);
				tv.setVisibility(TextView.VISIBLE);
				tv.setText("Introduzca el intervalo de envío de datos GPS");
			} else if (err.contains("GPSFETCHTIME_INCORRECT")) {
				tv = (TextView) findViewById(R.id.errorUserGpsFetchTime);
				tv.setVisibility(TextView.VISIBLE);
				tv.setText("El intervalo de envío de datos GPS tiene un formato incorrecto");
			} else if (err.contains("GPSFETCHTIME_TOOSMALL")) {
				tv = (TextView) findViewById(R.id.errorUserGpsFetchTime);
				tv.setVisibility(TextView.VISIBLE);
				tv.setText("El intervalo de envío de datos GPS es demasiado alto. Debe encontrarse entre 1000 y 5000 milisegundos");
			} else if (err.contains("GPSFETCHTIME_TOOBIG")) {
				tv = (TextView) findViewById(R.id.errorUserGpsFetchTime);
				tv.setVisibility(TextView.VISIBLE);
				tv.setText("El intervalo de envío de datos GPS es demasiado alto. Debe encontrarse entre 1000 y 5000 milisegundos");
			} else {
				tv = (TextView) findViewById(R.id.errorUserUnknown);
				tv.setVisibility(TextView.VISIBLE);
				tv.setText("Ha ocurrido un error inexperado: [" + err + "]");
			}

		}

	}

	/**
	 * 
	 */
	private void hideAllResponseErrorMessages() {
		((TextView) findViewById(R.id.errorUserFirstName)).setVisibility(TextView.GONE);
		((TextView) findViewById(R.id.errorUserLastName)).setVisibility(TextView.GONE);
		((TextView) findViewById(R.id.errorUserEmail)).setVisibility(TextView.GONE);
		((TextView) findViewById(R.id.errorUserGpsFetchTime)).setVisibility(TextView.GONE);
		((TextView) findViewById(R.id.errorUserVehicleType)).setVisibility(TextView.GONE);
		((TextView) findViewById(R.id.errorUserUnknown)).setVisibility(TextView.GONE);
		((TextView) findViewById(R.id.configureUserGeneralErrorMsg)).setVisibility(TextView.GONE);
	}

	@Override
	public void onTaskComplete(String result) {

	}
}